package net.sxnic.workflow.task;

import java.util.Date;
import java.util.List;

import net.sxinfo.core.dao.Page;
import net.sxinfo.core.dao.hibernate3.HibernateCriteria;
import net.sxinfo.core.dao.hibernate3.HibernateDaoUtils;
import net.sxinfo.core.dao.hibernate3.HibernateOrder;
import net.sxinfo.core.spring25.Dao;
import net.sxinfo.core.spring25.DefaultManager;
import net.sxnic.comm.basecode.BaseCodeUtils;
import net.sxnic.comm.sms.Sms;
import net.sxnic.comm.sms.SmsManager;
import net.sxnic.item.mdata.Mdata;
import net.sxnic.item.mdata.MdataManager;
import net.sxnic.ugr.user.UserManager;
import net.sxnic.workflow.node.Node;
import net.sxnic.workflow.node.NodeManager;
import net.sxnic.workflow.node.dao.NodeDao;
import net.sxnic.workflow.pd.Pd;
import net.sxnic.workflow.pd.PdManager;
import net.sxnic.workflow.pi.PiManager;
import net.sxnic.workflow.task.dao.TaskDao;
import net.sxnic.workflow.transition.TransitionManager;

import org.apache.commons.lang.StringUtils;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 
 * Comments: Task 业务层 实现
 * <p>
 * Author：孙宇飞
 * <p>
 * Create Date：2009-10-14
 * <p>
 * 
 * 
 */
@Service("taskManager")
public class DefaultTaskManager extends DefaultManager<Task, TaskDao, String>
		implements TaskManager {

	private static Logger logger = LoggerFactory
			.getLogger(DefaultTaskManager.class);

	@Autowired
	private TaskDao taskDao;

	@Autowired
	private SmsManager smsManager;

	@Autowired
	private NodeDao nodeDao;

	@Autowired
	private UserManager userManager;

	@Autowired
	private NodeManager nodeManager;

	@Autowired
	private PdManager pdManager;

	@Autowired
	private PiManager piManager;
	
	@Autowired
	private MdataManager wfeManager;
	
	@Autowired
	private TransitionManager trsManager;

	@Override
	protected Dao<Task, String> getEntityDao() {
		return taskDao;
	}

	@Override
	public void endTask(String taskId) throws TaskException,
			TaskStatusException {

		Task task = taskDao.get(taskId);

		if (Task.TASK_STATUS_ENDED.equals(task.getStatus())) {
			throw new TaskStatusException("任务已经是结束状态，不能再次结束 。");
		}

		task.setEndDate(new Date());
		task.setStatus(Task.TASK_STATUS_ENDED);
		taskDao.save(task);

		logger.debug("=={}===已结束，无接收人===", task.getId());
	}

	@Override
	public boolean cancelTask(String taskId, String operator) throws Exception {

		boolean canCancel = true;
		Task task = taskDao.get(taskId);
		// TODO 权限验证，必须是自己的任务

		if (!Task.TASK_STATUS_ENDED.equals(task.getStatus())) {
			throw new TaskException("只有结束的任务才能撤销！");
		}

		List<Task> list = taskDao.findBy("fromTask", task);
		logger.debug("list size = {}, status ={} ", list.size(),
				task.getStatus());

		String startNode = "";

		for (Task t : list) {
			if (t.getAssignee().equals(t.getFromTask().getAssignee())
					&& task.getName().equals(startNode)) {
				continue;
			}

			if (Task.TASK_STATUS_ENDED.equals(t.getStatus())) {
				logger.debug("==不能进行撤销操作。===后续{}的任务task status = {}",
						t.getAssignee(), t.getStatus());
				return false;
			}
		}

		if (canCancel) {
			// BeanUtils.copyProperties(temp, task);
			task.setOutcomeOperator(operator);
			task.setOutcomeOperateDate(new Date());
			// task.setCreationDate(new Date()); // 重新设置创建时间
			task.setEndDate(null);
			task.setStatus(Task.TASK_STATUS_ACTIVE);
			task.setOutcomeOperateReason("");
			taskDao.update(task);

			// 系统消息
			sendSms(task);

			for (Task t : list) {
				if (t.getAssignee().equals(t.getFromTask().getAssignee())
						&& t.getName().equals(startNode)) {
					continue;
				}

				t.setStatus(Task.TASK_STATUS_CANCELED);
				// TODO 原因
				t.setOutcomeOperateReason("");
				t.setOutcomeOperator(task.getAssignee());
				t.setOutcomeOperateDate(new Date());
				taskDao.update(t);

				smsManager.deleteByEntityId(t.getId());
			}			
		}
	
		return canCancel;
	}

	@Override
	public void deleteTask(Task task, String operator) {
		task.setOutcomeOperator(operator);
		task.setOutcomeOperateDate(new Date());
		task.setStatus(Task.TASK_STATUS_DELETED);

		taskDao.save(task);
	}

	@Override
	public void reactiveTask(Task task, String operator) {
		if (!Task.TASK_STATUS_SUSPENDED.equals(task.getStatus())) {
			return;
		}

		task.setOutcomeOperator(operator);
		task.setOutcomeOperateDate(new Date());
		task.setStatus(Task.TASK_STATUS_CANCELED);

		taskDao.save(task);
	}

	@Override
	public void suspendTask(Task task, String operator) {
		if (!Task.TASK_STATUS_ACTIVE.equals(task.getStatus())) {
			return;
		}

		task.setOutcomeOperator(operator);
		task.setOutcomeOperateDate(new Date());
		task.setStatus(Task.TASK_STATUS_CANCELED);

		taskDao.save(task);
	}


	@Override
	public void endTask(Task task, String nextAssignee, String comment)
			throws TaskException, TaskStatusException {

		if (task == null) {
			throw new TaskStatusException("任务实例为null，操作返回 。");
		}

		// 验证状态
		if (Task.TASK_STATUS_ENDED.equals(task.getStatus())) {
			throw new TaskStatusException("任务已经是结束状态，不能再次结束 。");
		}

		// TODO 是否发送系统消息

		// TODO 催办督办
		// 置换意见中的半角标点
		if (StringUtils.isNotBlank(comment)) {
			comment = comment.replace(",", "，").replace(".", "。");
		}
		
		task.setComments(comment);

		task.setEndDate(new Date());
		task.setStatus(Task.TASK_STATUS_ENDED);
		taskDao.update(task);

		if (StringUtils.isBlank(nextAssignee)) {
			return;
		}
		
		this.createTask(null, nextAssignee, task);		
	}

	@Override
	public void returnBack(String taskId, String continueType, String reason) {
		String nextAssignee = "";
		// 结束当前任务
		Task task = taskDao.get(taskId);

		if (task == null) {
			throw new TaskStatusException("任务实例为null，操作返回 。");
		}

		// 验证状态
		if (Task.TASK_STATUS_ENDED.equals(task.getStatus())) {
			throw new TaskStatusException("任务已经是结束状态，不能再次结束 。");
		}

		if (StringUtils.isBlank(continueType)) {
			continueType = Task.RETURNBACK_CONTINUE_TYPE_CONTINUE;
		}

		Pd pd = pdManager.findLatestPdByName(task.getProcessName());
		String startNodeName = nodeManager.findStartNode(pd).getName();

		// 查询当前任务前的所有任务,置为退回状态
		List<Task> tasklist = taskDao.findBy("entityId", task.getMdata().getId());
		logger.debug("task:{}" + task.getId());
		logger.debug("tasklist:{}" + tasklist.size());
		for (Task t : tasklist) {
			if (startNodeName.equals(t.getName()))
				nextAssignee = t.getAssignee();
		}
		// 查询当前任务前的所有任务,置为退回状态
		for (Task t : tasklist) {
			if (startNodeName.equals(t.getName()))
				nextAssignee = t.getAssignee();
			t.setStatus(Task.TASK_STATUS_RETURNBACK);
			taskDao.update(t);
		}
		// 给拟稿人员创建任务 (可以删除，查看退回意见)
		
		task.setComments(reason);
		task.setEndDate(new Date());
		task.setStatus(Task.TASK_STATUS_RETURNBACK);
		taskDao.update(task);

		Node nextNode = nodeManager.findByPdName(task.getProcessName(),
				startNodeName);

		Task destTask = createTask(nextNode, nextAssignee, task);

		destTask.setReturnBack(true);
		// destTask.setComments(reason);
		destTask.setReturnBackFromMan(task.getAssignee());
		destTask.setReturnBackFromNode(task.getName());
		destTask.setContinueType(continueType);

		taskDao.update(destTask);
	}

	@Override
	public void updateComment(String taskId, String taskComment) {
		Task task = taskDao.get(taskId);
		if (task == null) {
			throw new TaskException("task id is null");
		}

		task.setComments(taskComment);

		taskDao.update(task);
	}

	@Override
	public void returnBack(String taskId, String toNodeName, String toAssignee,
			String continueType, String comment) {
		// 结束当前任务
		Task task = taskDao.get(taskId);

		if (task == null) {
			throw new TaskStatusException("任务实例为null，操作返回 。");
		}

		// 验证状态
		if (Task.TASK_STATUS_ENDED.equals(task.getStatus())) {
			throw new TaskStatusException("任务已经是结束状态，不能再次结束 。");
		}

		// 查询当前任务前的所有任务,置为退回状态
		List<Task> tasklist = taskDao.findBy("entity", task.getMdata().getId());

		for (Task t : tasklist) {
			t.setStatus(Task.TASK_STATUS_RETURNBACK);
			taskDao.update(t);
			smsManager.deleteByEntityId(t.getId());
		}

		Node nextNode = nodeManager.findByPdName(task.getProcessName(),
				toNodeName);

		this.createTask(nextNode, toAssignee, task);

	}

	@Override
	public void deleteTask(String taskId) {
		Task t = taskDao.get(taskId);
		t.setEnabled(false);
		taskDao.update(t);
	}

	@Override
	public Task findFirstTask(String entityId) {
		return taskDao.findFirstTask(entityId);
	}

	@Override
	public Page getPageByUserName(int page, int pageSize, String userName,
			String type) {
		HibernateOrder infoCodeOrder = HibernateDaoUtils.createHibernateOrder(
				"status", true);
		HibernateCriteria hc = new HibernateCriteria().add(infoCodeOrder);

		infoCodeOrder = HibernateDaoUtils.createHibernateOrder("creationDate",
				false);

		hc.add(infoCodeOrder);
		HibernateOrder uorder = HibernateDaoUtils.createHibernateOrder(
				"userOrder", true);

		hc.add(uorder);

		Criterion dc = null;

		dc = Restrictions.eq("assignee", userName);
		hc.add(dc);

		dc = Restrictions.eq("flag", true);
		hc.add(dc);

		dc = Restrictions.in("status", new Object[] { Task.TASK_STATUS_ENDED,
				Task.TASK_STATUS_ACTIVE });
		hc.add(dc);

		return this.getPageByCriteria(page, pageSize, hc);
	}
	

	@Override
	public Task findReturnBackTask(String processId, String assignee) {
		return null;
	}


	/**
	 * 向消息系统提交信息，便于系统提示
	 * 
	 * @param task
	 */
	private void sendSms(Task task) {
		if (!Task.TASK_STATUS_ACTIVE.equals(task.getStatus())) {
			return;
		}
		Sms sms = new Sms();
		List<Sms> list = smsManager.findBy("entityId", task.getId());
		if (list != null && list.size() > 0) {
			sms = list.get(0);
		}
		Mdata entity = task.getMdata();
		sms.setModule("task");
		sms.setTitle(BaseCodeUtils.getInfoName("030", task.getProcessName())
				+ ":新的待办任务。标题：" + entity.getAppName());
		sms.setReceiver(task.getAssignee());
		sms.setContent(entity.getAppName());
		sms.setUrl("/task/treat.jspa?taskId=" + task.getId());
		sms.setEntityId(task.getId());

		smsManager.save(sms);

		logger.debug("向消息系统发送“新任务提示”成功==taskId==" + task.getId());
	}

	

	@Override
	public Task createTask(Node node, String assignee, Task fromTask) {
		
		Task task = new Task(node.getName(), assignee);
		
		// 开始创建任务
		task.setNode(node);
		task.setProcessName(fromTask.getProcessName());
		task.setMdata(fromTask.getMdata());	
		taskDao.save(task);
		task.setFromTask(fromTask);

		// 向消息系统发送
		sendSms(task);

		logger.debug("{} create task for {} success!",
				new String[] { fromTask.getAssignee(), assignee });

		return task;
	}

	@Override
	public Task createSelfTaskatStartNode(String entityId, String CatalogAlias, String assignee) {

		Pd pd = pdManager.findLatestPdByName(CatalogAlias);
		Node startNode = nodeManager.findStartNode(pd);
		//User user = userManager.getUserByUsername(assignee);
		Mdata entity = wfeManager.get(entityId);		

		Task task = new Task(startNode.getName(), assignee);
		//task.setDept(user.getDept().getCode());
		task.setProcessName(CatalogAlias);		
		task.setNode(startNode);
		task.setMdata(entity);
		
		taskDao.save(task);

		logger.debug("{} create self task at {} success!", new String[] {
				assignee, startNode.getName() });

		return task;
	}
	
}
